package com.atstudying.mallsearch.thread;

import java.util.concurrent.*;

/**
 * @author Mr.zhneg
 * @create 2020-11-06-0:29
 */
public class ThreadTest {

    //我们自己创建的一个线程池
    public static ExecutorService executor= Executors.newFixedThreadPool(10);

    //多任务组合
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        CompletableFuture<String> futureimg = CompletableFuture.supplyAsync(() -> {

            System.out.println("查询商品图片信息");
            return "hello.jpg";
        }, executor);

        CompletableFuture<String> futureAttr = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品属性");

            return "黑色+256G";
        }, executor);
        CompletableFuture<String> futureDesc = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品介绍");

            return "华为";
        }, executor);

//        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.allOf(futureAttr, futureDesc, futureimg);
////        voidCompletableFuture.get();
//        System.out.println("main。。。end"+futureAttr.get()+futureDesc.get()+futureimg.get());
        CompletableFuture<Object> objectCompletableFuture = CompletableFuture.anyOf(futureAttr, futureDesc, futureimg);
        System.out.println("main。。。end"+objectCompletableFuture.get());

    }


    //两个任务中任意一个完成
    public static void thread06(String[] args) throws ExecutionException, InterruptedException {

        CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1开始：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("任务1结束：" + i);
            return i;
        }, executor);

        CompletableFuture<Integer> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2开始：" + Thread.currentThread().getId());
            int i = 10 / 5;
            try {
                Thread.sleep(3000000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务2结束：" + i);
            return i;
        }, executor);

        CompletableFuture<String> applyToEither = future02.applyToEither(future01, (result) -> {
            return "任务2没完成，任务一完成了：返回结果：" + result;

        });
        System.out.println(applyToEither.get());

//        future02.acceptEither(future01,(result)->{
//                        System.out.println("任务2没完成，任务一完成了：返回结果："+result );
//
//        });
//        future01.runAfterEither(future02,()->{
//            System.out.println("任务2没完成，任务一完成了" );
//
//        });
    }


    //两个都完成
    public static void thread05(String[] args) throws ExecutionException, InterruptedException {

        CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1开始：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("任务1介绍：" + i);
            return i;
        }, executor);

        CompletableFuture<Integer> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2开始：" + Thread.currentThread().getId());
            int i = 10 / 5;
            System.out.println("任务2结束：" + i);
            return i;
        }, executor);
        CompletableFuture<String> completableFuture = future01.thenCombine(future02, (f1, f2) -> {
            //  R apply(T t, U u);

            return f1 + ".." + f2 + "->thenCombine";
        });
        System.out.println(completableFuture.get());
//        future01.thenAcceptBoth(future02,(result,exec)->{
//            System.out.println("结果是："+result+"异常是："+exec);
//        });
//        future01.runAfterBoth(future02,()->{
//
//            System.out.println("任务1，任务2都完成。。。");
//        });
    }

    //线程串行化测试
    public static void thread04(String[] args) throws ExecutionException, InterruptedException {

        //thenRun不可以获取到上一步的返回结果
        CompletableFuture<Void> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
            return i;
        }, executor).thenRun(() -> {
            System.out.println("任务2启动。。。");

        });

        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
            return i;
        }, executor);
        //thenAccept：可以接受结果，无返回值

        future.thenAccept((result)->{

            System.out.println("运行结果：" + result);

        });

        //：thenApply可以接受上一步的结果，并且有返回值
        CompletableFuture<String> stringCompletableFuture = future.thenApply((reult) -> {
            if (reult == 5) {

                return reult + "thenApply";
            }
            return null;
        });
        System.out.println("thenApply运行结果：" + stringCompletableFuture.get());


    }


    //handle测试
        public static void thread03(String[] args) {
        System.out.println("main。。。。start..");

        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 0;
            System.out.println("运行结果：" + i);
            return i;
        }, executor).handleAsync((result,exec)->{

            /**
             * @FunctionalInterface
            public interface Function<T, R> {
            R apply(T t);
             */
            if (result!=null){
                return result;
            }else {
                System.out.println("异常"+exec);
                return 10;
            }
        });

        System.out.println("main。。。。end..");

    }

    //whenComplete测试
    public static void thread01(String[] args) throws ExecutionException, InterruptedException {

        System.out.println("main。。。。start..");

//        CompletableFuture.runAsync(()->{
//            System.out.println("当前线程："+Thread.currentThread().getId());
//            int i=10/2;
//            System.out.println("运行结果："+i);
//        },executor);

        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 0;
            System.out.println("运行结果：" + i);
            /**
             * @FunctionalInterface
            public interface Supplier<T> {

             * @return a result

            T get();
        }
             */
            return i;
        }, executor).whenComplete((res,exc)->{

            /**
             * @FunctionalInterface
            public interface BiConsumer<T, U> {

            void accept(T t, U u);
             */
            //虽然可以得到异常信息，但是没法返回修改数据
            System.out.println("异步任务成功完成：结果是："+res+"；异常是" + exc);
        }).exceptionally(throwable -> {

            /**
             * @FunctionalInterface
            public interface Function<T, R> {

            R apply(T t);
             */
            //可以感知异常，同时返回默认值
            return 10;
        });
        System.out.println("exceptionally运行的结果："+future.get());

//       System.out.println("supplyAsync运行的结果："+future.get());

        System.out.println("main。。。。end..");

//        new Runnable() {
//            @Override
//            public void run() {
//
//            }
//        }
    }

    /**创建线程池测试
     * 1：继承Thread
     *         Thread01 thread01 = new Thread01();
     thread01.start();
     * 2：实现runnable接口
     * //        Thread02 thread02=new Thread02();
     //        new Thread(thread02).start();
     * 3：实现callable接口+futureTask（可以拿到返回结果，可以处理异常)jdk1.5以后
     *         FutureTask<Integer> futureTask = new FutureTask<>(new Callable01());
     new Thread(futureTask).start();
     //等待整个线程执行完成，，获取返回结果
     Integer integer = futureTask.get();
     * 4：线程池
     * 给线程池直接提交任务
     *
     * @param args
     */
//    public static ExecutorService service= Executors.newFixedThreadPool(10);


    //线程创建测试
    public static void thread(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main。。。。start..");

//        service.execute(new Thread01());
        /**
         * int corePoolSize,：核心线程数【一直在除非（allowCoreThreadTimeOut）
         int maximumPoolSize,【200】最大线程数量；控制资源并发的
         long keepAliveTime,如果当前线程的数量大于core数量。
         释放空闲的线程。只要线程空闲（maximumPoolSize-corePoolSize）大于指定的keepAliveTime；
         TimeUnit unit, 时间单位
         BlockingQueue<Runnable> workQueue,阻塞队列。如果任务有很多，就会将目前多的任务放在队列里面。
         只要有线程空闲，就会去队列里面取出新的任务继续执行
         ThreadFactory threadFactory, 线程的创建工厂
         RejectedExecutionHandler handler：如果队列满了按照我们指定的拒绝策略拒绝执行任务
         */
//        ThreadPoolExecutor executor = new ThreadPoolExecutor(5,
//                200,
//                10,
//                TimeUnit.SECONDS,
//                new LinkedBlockingDeque<>(1000000),
//                Executors.defaultThreadFactory(),
//                null
//
//        );

//        ExecutorService service = Executors.newCachedThreadPool();
//        ExecutorService service = Executors.newFixedThreadPool();
//        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool();

//        ExecutorService service = Executors.newSingleThreadExecutor();
        System.out.println("main。。。。end..");

    }

    public static class Thread01 extends Thread{

        @Override
        public void run(){
            System.out.println("当前线程："+Thread.currentThread().getId());
            int i=10/2;
            System.out.println("运行结果："+i);

        }

    }

    public static class Thread02 implements Runnable {

        @Override
        public void run(){
            System.out.println("当前线程："+Thread.currentThread().getId());
            int i=10/2;
            System.out.println("运行结果："+i);

        }

    }
    public static class Callable01 implements Callable<Integer> {


        @Override
        public Integer call() throws Exception {
            System.out.println("当前线程："+Thread.currentThread().getId());
            int i=10/2;
            System.out.println("运行结果："+i);
            return i;

        }
    }
}
